package pyip.lib.javalearn.io.nio;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class RequestProcesser {

    private Selector selector;
    private ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 10, 10, TimeUnit.MINUTES, new ArrayBlockingQueue<Runnable>(100));

    public RequestProcesser(Selector selector) {
        this.selector = selector;
    }

    public void stop() {
        executor.shutdown();
    }

    public void doRequest(SelectionKey key) {
        executor.execute(new Worker(key, selector));
    }

    private class Worker implements Runnable {
        private SelectionKey key;
        private Selector selector;
        // TODO 每个worker都分配内存的方式是否可以改进
        private ByteBuffer readBuf = ByteBuffer.allocate(BUF_SIZE);

        private static final int BUF_SIZE = 10240;

        public Worker(SelectionKey key, Selector selector) {
            this.key = key;
            this.selector = selector;
        }

        @Override
        public void run() {
            SocketChannel socketChannel = (SocketChannel) key.channel();
            if (!socketChannel.isOpen()) {
                return;
            }

            try {
                int count = 0;
                do {
                    readBuf.clear();
                    count = socketChannel.read(readBuf);
                    System.out.println("read count " + count);
                    if (count > 0) {
                        readBuf.flip();
                        String content = new String(readBuf.array(), 0, 2, "utf-8");
                        if (content.equalsIgnoreCase("!n")) {
                            // ignore
                        } else if (content.equalsIgnoreCase("!w")) {// 注册写
                            key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
                        } else {
                            // 输出客户端请求的数据
                            System.out.println("client 客户端: " + new String(readBuf.array(), 0, readBuf.remaining(), "utf-8"));

                            // 把客户端的数据直接写回客户端
                            while (readBuf.hasRemaining()) {
                                socketChannel.write(readBuf);
                            }
                        }
                    }
                } while (count == BUF_SIZE);
            } catch (IOException e) {
                e.printStackTrace();
                // 取消读监听, 否则对于客户端异常断开的socket会一直读就绪
                // TODO 这种处理方式正确吗? 需要关闭channel吗 ?
                key.cancel();
                try {
                    socketChannel.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                return;
            } finally {
                // 再次注册读
                key.interestOps(key.interestOps() | SelectionKey.OP_READ);
            }
        }

    }
}
